package com.sprouting.ops.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.ops.annotations.invoke.IdempotentSingle;
import com.sprouting.ops.interfaces.AddGroup;
import com.sprouting.ops.interfaces.ConstantBase;
import com.sprouting.ops.interfaces.UpdGroup;
import com.sprouting.ops.model.*;
import com.sprouting.ops.model.bo.OpsDeployComputerBo;
import com.sprouting.ops.model.qo.OpsDeployQo;
import com.sprouting.ops.service.*;
import com.sprouting.ops.utils.CheckTool;
import com.sprouting.ops.utils.EntityTool;
import com.sprouting.ops.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 部署信息表-组件和组件;(OpsDeploy)(OPS_DEPLOY) 表控制层
 *
 * @author ：lx（长沙麓谷）
 * @date 创建时间：2025-06-29 22:18:44
 */
@Slf4j
@RestController
@RequestMapping("opsDeploy")
public class OpsDeployController {

    @Resource
    private OpsDeployService opsDeployService;
    @Resource
    private OpsComputerServerService opsComputerServerService;
    @Resource
    private OpsAppBranchService opsAppBranchService;
    @Resource
    private OpsComponentVersionService opsComponentVersionService;
    @Resource
    private OpsEnvService opsEnvService;
    @Resource
    private DromaraFileStorageService dromaraFileStorageService;
    @Resource
    private OpsDeployLinkService opsDeployLinkService;


    /**
     * 分页查询部署信息表-组件和应用
     * @param query 查询参数
     * @return
     */
    @PostMapping("getListPage")
    public ResultJson getListPage(OpsDeployQo query){
        Page page = query.getPage();
        return ResultJson.success(opsDeployService.getListPage(page, query));
    }

    /**
     * 删除部署信息表-组件和应用
     * @param id 部署信息表-组件和组件
     * @return
     */
    @PostMapping("delOpsDeploy")
    @IdempotentSingle
    public ResultJson delOpsDeploy(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorCheck();
        }

        List<DromaraFileStorage> bindList = dromaraFileStorageService.getByBindId(id);

        opsDeployService.delOpsDeploy(id, bindList);
        return ResultJson.success();
    }

    /**
     * 组件解绑-只适合组件，组件才有多个关联，应用不存在
     * 部署id可能关联多个环境，如果只有一个关联的时候，同时删除对应的部署信息
     * 如果有多个，只解除这一个绑定关系
     * @param opsDeployId 部署id
     * @param envId 环境id
     * @return
     */
    @PostMapping("unbindOpsComponent")
    @IdempotentSingle
    public ResultJson unbindOpsComponent(String opsDeployId, String envId){
        if (CheckTool.checkNull(opsDeployId, envId)){
            return ResultJson.errorCheck();
        }

        int bindNum = 0;
        List<OpsDeployLink> list = opsDeployLinkService.getByOpsDeployId(opsDeployId);
        if (CollUtil.isNotEmpty(list)){
            bindNum = list.size();
        }

        if (bindNum <= 1){
            // 需要删除绑定关系
            List<DromaraFileStorage> bindList = dromaraFileStorageService.getByBindId(opsDeployId);
            opsDeployService.delOpsDeploy(opsDeployId, bindList);
        } else {
            // 解除绑定关系
            LambdaUpdateWrapper<OpsDeployLink> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(OpsDeployLink::getOpsDeployId, opsDeployId);
            wrapper.eq(OpsDeployLink::getEnvId, envId);
            opsDeployLinkService.remove(wrapper);
        }

        return ResultJson.success();
    }

    /**
     * 更新部署信息表-组件和组件;
     * @param bo 修改参数
     * @return
     */
    @PostMapping("updOpsDeploy")
    @IdempotentSingle
    public ResultJson updOpsDeploy(@Validated(UpdGroup.class) OpsDeployComputerBo bo){
        String msg = checkOpsDeploy(bo);
        if (msg != null){
            return ResultJson.error(msg);
        }

        // 修改的时候不让去动环境信息
        OpsDeploy opsDeploy = BeanUtil.copyProperties(bo, OpsDeploy.class);
        EntityTool.updBase(opsDeploy);

        // 提取Markdown的数据
        // 修改的时候也要提取，然后转换为生产的数据，这里要注意的是，修改的时候，不考虑去删除旧的数据的问题，到时候删除的时候，直接使用objId统一处理即可，因为这个数据量还是比较小的，没必要找的旧的去删，新的去加，搞麻烦了
        List<DromaraFileStorage> list = getMarkdownImage(opsDeploy);

        opsDeployService.updOpsDeploy(opsDeploy, list);
        return ResultJson.success(bo);
    }

    /**
     * 保存部署信息表-组件和组件;
     * 计算机中选应用的保存，一种应用选计算机的保存，这里是 计算机选应用
     * @param bo 保存参数
     * @return
     */
    @PostMapping("saveOpsDeploy")
    @IdempotentSingle
    public ResultJson saveOpsDeploy(@Validated(AddGroup.class) OpsDeployComputerBo bo){
        String msg = checkOpsDeploy(bo);
        if (msg != null){
            return ResultJson.error(msg);
        }

        OpsDeploy opsDeploy = BeanUtil.copyProperties(bo, OpsDeploy.class);
        opsDeploy.setId(IdTool.getId());
        EntityTool.saveBase(opsDeploy);

        // 补充场所id
        OpsComputerServer server = opsComputerServerService.getById(opsDeploy.getComputerServerId());
        opsDeploy.setSiteId(server.getSiteId());
        // 补充版本信息
        if (ConstantBase.OpsDeployType.APP.equals(bo.getType())){
            OpsAppBranch appBranch = opsAppBranchService.getById(bo.getAppBranchId());
            opsDeploy.setAppId(appBranch.getAppId());

        } else if (ConstantBase.OpsDeployType.COMPONENT.equals(bo.getType())){
            OpsComponentVersion componentVersion = opsComponentVersionService.getById(bo.getComponentVersionId());
            bo.setComponentId(componentVersion.getComponentId());
        }

        // 补充环境信息
        OpsDeployLink deployLink = new OpsDeployLink();
        deployLink.setId(IdTool.getId());
        deployLink.setOpsDeployId(opsDeploy.getId());
        deployLink.setEnvId(bo.getEnvId());
        OpsEnv env = opsEnvService.getById(bo.getEnvId());
        deployLink.setProductId(env.getProductId());

        // 提取Markdown的数据
        List<DromaraFileStorage> list = getMarkdownImage(opsDeploy);
        opsDeployService.saveOpsDeploy(opsDeploy, deployLink, list);
        return ResultJson.success(bo);
    }

    /**
     * 获取图片信息
     * @param opsDeploy 部署信息
     * @return 提取到的图片信息用于转正式
     */
    private List<DromaraFileStorage> getMarkdownImage(OpsDeploy opsDeploy) {
        List<DromaraFileStorage> list = new ArrayList<>();
        List<DromaraFileStorage> startEndlList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsDeploy.getStartEnd(), opsDeploy.getId(), ConstantBase.FileSourceType.DEPLOY_START_END);
        if (CollUtil.isNotEmpty(startEndlList)){
            list.addAll(startEndlList);
        }
        List<DromaraFileStorage> deployProcesstList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsDeploy.getDeployProcess(), opsDeploy.getId(), ConstantBase.FileSourceType.DEPLOY_PROCESS);
        if (CollUtil.isNotEmpty(deployProcesstList)){
            list.addAll(deployProcesstList);
        }
        List<DromaraFileStorage> verificationList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsDeploy.getVerification(), opsDeploy.getId(), ConstantBase.FileSourceType.DEPLOY_VERIFICATION);
        if (CollUtil.isNotEmpty(verificationList)){
            list.addAll(verificationList);
        }

        return list;
    }

    // todo 获取计算机部署的应用，寻找公共的组件
    // todo 获取可选的应用和组件
    // todo 直接绑定组件的情况，不绑定组件的情况


    /**
     * 部署信息表-组件和组件;数据校验
     * @param bo 部署信息表-组件和组件; 校验数据
     * @return 非null则有错误
     */
    private String checkOpsDeploy(OpsDeployComputerBo bo){
        if (ConstantBase.OpsDeployType.APP.equals(bo.getType())){
            // if (CheckTool.checkNull(bo.getAppId())){
            //     return "应用不能为空";
            // }
            if (CheckTool.checkNull(bo.getAppBranchId())){
                return "应用分支不能为空";
            }

        } else if (ConstantBase.OpsDeployType.COMPONENT.equals(bo.getType())){
            // if (CheckTool.checkNull(bo.getComponentId())){
            //     return "组件不能为空";
            // }
            if (CheckTool.checkNull(bo.getComponentVersionId())){
                return "组件版本不能为空";
            }
        }

        return null;
    }

}
